package lines.gameengine.tracer;

import lines.gameengine.Ball;
import lines.gameengine.FieldPoint;
import lines.gameengine.stub.StubField;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

/**
 * @author vpotapenko
 */
public class FieldTracerTest {

    private FieldTracer tracer;
    private StubField field;

    @Before
    public void setUp() throws Exception {
        tracer = new FieldTracer();
        field = new StubField(9, 9);
    }

    @Test public void shouldFindTraceOnPeerCells() {
        tracer.update(field);

        SearchResult result = tracer.findTrace(new FieldPoint(0, 0), new FieldPoint(0, 1));
        assertThat(result.hasTrace(), equalTo(true));

        List<FieldPoint> trace = result.getTrace();
        assertThat(trace.size(), equalTo(2));
        assertThat(trace.get(0), equalTo(new FieldPoint(0, 0)));
        assertThat(trace.get(1), equalTo(new FieldPoint(0, 1)));
    }

    @Test public void shouldFindSimpleStraightTrace() {
        tracer.update(field);

        SearchResult result = tracer.findTrace(new FieldPoint(3, 3), new FieldPoint(3, 7));
        assertThat(result.hasTrace(), equalTo(true));

        List<FieldPoint> trace = result.getTrace();
        assertThat(trace.size(), equalTo(5));
        assertThat(trace.get(0), equalTo(new FieldPoint(3, 3)));
        assertThat(trace.get(1), equalTo(new FieldPoint(3, 4)));
        assertThat(trace.get(2), equalTo(new FieldPoint(3, 5)));
        assertThat(trace.get(3), equalTo(new FieldPoint(3, 6)));
        assertThat(trace.get(4), equalTo(new FieldPoint(3, 7)));
    }

    @Test public void shouldFindSimpleTraceWithTurn() {
        tracer.update(field);

        SearchResult result = tracer.findTrace(new FieldPoint(3, 3), new FieldPoint(5, 5));
        assertThat(result.hasTrace(), equalTo(true));

        List<FieldPoint> trace = result.getTrace();
        assertThat(trace.size(), equalTo(5));

        assertThat(trace.get(0), equalTo(new FieldPoint(3, 3)));
        assertThat(trace.get(1), equalTo(new FieldPoint(3, 4)));
        assertThat(trace.get(2), equalTo(new FieldPoint(3, 5)));
        assertThat(trace.get(3), equalTo(new FieldPoint(4, 5)));
        assertThat(trace.get(4), equalTo(new FieldPoint(5, 5)));
    }

    @Test public void shouldFindTraceWithBusyCells() {
        field.getCell(3, 0).setBall(new Ball(null));
        field.getCell(3, 1).setBall(new Ball(null));
        field.getCell(3, 2).setBall(new Ball(null));
        field.getCell(3, 3).setBall(new Ball(null));
        field.getCell(2, 3).setBall(new Ball(null));
        field.getCell(1, 3).setBall(new Ball(null));

        tracer.update(field);

        SearchResult result = tracer.findTrace(new FieldPoint(0, 0), new FieldPoint(5, 5));
        assertThat(result.hasTrace(), equalTo(true));

        List<FieldPoint> trace = result.getTrace();
        assertThat(trace.size(), equalTo(11));

        assertThat(trace.get(0), equalTo(new FieldPoint(0, 0)));
        assertThat(trace.get(1), equalTo(new FieldPoint(0, 1)));
        assertThat(trace.get(2), equalTo(new FieldPoint(0, 2)));
        assertThat(trace.get(3), equalTo(new FieldPoint(0, 3)));
        assertThat(trace.get(4), equalTo(new FieldPoint(0, 4)));
        assertThat(trace.get(5), equalTo(new FieldPoint(0, 5)));
        assertThat(trace.get(6), equalTo(new FieldPoint(1, 5)));
        assertThat(trace.get(7), equalTo(new FieldPoint(2, 5)));
        assertThat(trace.get(8), equalTo(new FieldPoint(3, 5)));
        assertThat(trace.get(9), equalTo(new FieldPoint(4, 5)));
        assertThat(trace.get(10), equalTo(new FieldPoint(5, 5)));
    }

    @Test public void shouldNotFindTraceWithAllBusyCells() {
        field.getCell(3, 0).setBall(new Ball(null));
        field.getCell(3, 1).setBall(new Ball(null));
        field.getCell(3, 2).setBall(new Ball(null));
        field.getCell(3, 3).setBall(new Ball(null));
        field.getCell(2, 3).setBall(new Ball(null));
        field.getCell(1, 3).setBall(new Ball(null));
        field.getCell(0, 3).setBall(new Ball(null));

        tracer.update(field);

        SearchResult result = tracer.findTrace(new FieldPoint(0, 0), new FieldPoint(5, 5));
        assertThat(result.hasTrace(), equalTo(false));
    }
}
